/***********************************************************
 * Main Test
 * Programmers:
 *		Cory Frey
 *		Kendra Konopka
 *		Charles Leichner
 *		Andrew Weatherly
 *
 * Date:
 *		6 December 2010
 *
 * Description:
 *		This file tests the various functions implemented in
 *		the Matrix.h and MatlabPrinter.h libraries.
 *
 ***********************************************************/

#include "Matrix.h"
#include "MatlabPrinter.h"
#include <iostream>
#include <vector>

using namespace std;

int main(){

	// Every matrix has 3 data members, the number of rows, the number of columns (both ints), and the elements. 
	// This elements are represented as a vector<vector<double> >, and can be access with the operator() parameter.

	///////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////////////////////////
	////////////														   				   ////////////
	////////////				ADD YOUR TEST TO THE BOTTOM OF THIS FILE!!!!!			   ////////////
	////////////																		   ////////////
	///////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////////////////////////


	// Matricies for input are located in the matrices file inside of the build directory	
	Matrix matrixA("A_4by4.max");
	Matrix matrixB("B_4by4.max");
	cout << "matrixA is:"<<endl;
	cout << matrixA << endl;

    if( matrixA.isSquare() ){
        cout << "matrixA is square and the trace is: "<< matrixA.trace() <<endl;
    }
	
	Matrix matrixF("A_3by3.max");
	cout<< "The 1st eigen value of F is " <<matrixF.eigenValues().at(0) << " and the RREF matrix for that value is:" << endl;
	cout << (matrixF.eigenVectors().at(0)).rref();
	cout<< "The 2nd eigen value of F is " <<matrixF.eigenValues().at(1) << " and the RREF matrix for that value is:" <<endl;
	cout << (matrixF.eigenVectors().at(1)).rref();
	cout<< "The 3rd eigen value of F is " <<matrixF.eigenValues().at(2) << " and the RREF matrix for that value is:" <<endl;
	cout << (matrixF.eigenVectors().at(2)).rref();
		
	/*
	vector<vector<double> > input;
	for (int i = 0; i < 2; i++){
		for (int j = 0; j < 3; j++){
			input.at(i).at(j) = i+j;
		}
	}
	*/
	cout << "Transpose of A is: " << endl;
	cout << matrixA.transpose() << endl;

	cout << "Negative of A is:" << endl;
	matrixA = -matrixA;
	cout << matrixA << endl;

	cout << "matrixA scaled by -2 is: "<< endl;
	cout << -2*matrixA << endl;
	
	cout << "Creating an Identity matrix of size 4: " << endl << Matrix::identity(4) << endl;
		
	// Testing Power
	Matrix matrixC("C_4by4.max");
	cout <<"matrixC is: "<< endl;
	cout << matrixC << endl;
	cout << "matrixC^2 is: " <<endl;
	cout << matrixC.Mpow(2) << endl;

	cout << "Determinant of A is: " << matrixA.determinant() << endl;
	
	cout << "inverse of A is:" << endl;
	cout << matrixA.inverse() << endl;

	// this will be the operator+ method
	Matrix matrixD = matrixA + matrixB;

    cout << "The sum of matrixA + matrixB is:" << endl;
	cout << matrixD <<endl;

    cout << "The difference of matrixD - matrixA is:" << endl;
	cout << matrixD - matrixA <<endl;

	cout << "Echelon form:"<< endl;
	cout <<matrixA.echelon()<<endl;

	cout << "L factorization:"<< endl;
	cout <<matrixA.Lfact()<<endl;

	cout << "U factorization:"<< endl;
	cout <<matrixA.Ufact()<<endl;

	cout << "LU"<< endl;
	cout <<matrixA.Lfact()*matrixA.Ufact()<<endl;

	cout << "Q factorization:"<< endl;
	cout <<matrixA.Qfact()<<endl;

	cout << "R factorization:"<< endl;
	cout <<matrixA.Rfact()<<endl;

    if(matrixA == matrixA) {
        cout << "== works" << endl;
    }
    else{
        cout << "== doesn't work" << endl;
    }



	// This will test all of the functionality of the MatlabPrinter class
	MatlabPrinter printer("Matlab_Output.m");
	printer.writeToFile();



	return 0;
}
